using Digitalmes.Common.Models;

namespace Digitalmes.Common.Utils;

/// <summary>
/// 文件操作帮助类
/// </summary>
public static class FileUtils
{
    /// <summary>
    /// 如果不存在目录，则创建。
    /// </summary>
    /// <param name="path">要创建的目录路径</param>
    public static void CreateDirectoryIfNotExists(string path)
    {
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }

    /// <summary>
    /// 返回文件扩展名，不含“.”
    /// </summary>
    /// <param name="filepath">文件全名称</param>
    /// <returns>string</returns>
    public static string GetFileExt(string filepath)
    {
        var ext = Path.GetExtension(filepath) ?? "";
        if (ext[0] == '.')
        {
            return ext[1..];
        }
        return ext;
    }

    /// <summary>
    /// 若存在指定文件，则删除。
    /// </summary>
    /// <param name="filePath">文件的绝对路径</param>
    public static void DeleteFileIfExists(string filePath)
    {
        if (File.Exists(filePath))
        {
            File.Delete(filePath);
        }
    }

    /// <summary>
    /// 若存在指定目录，则删除。
    /// </summary>
    /// <param name="directoryPath">目录的绝对路径</param>
    public static void DeleteDirectoryIfExists(string directoryPath)
    {
        if (Directory.Exists(directoryPath))
        {
            Directory.Delete(directoryPath);
        }
    }

    /// <summary>
    /// 清空指定目录下所有文件及子目录。
    /// </summary>
    /// <param name="directoryPath">指定目录的绝对路径</param>
    public static void ClearDirectory(string directoryPath)
    {
        if (!Directory.Exists(directoryPath)) 
            return;

        //删除目录中所有的文件
        string[] files = Directory.GetFiles(directoryPath);
        for (int i = 0; i < files.Length; i++)
        {
            File.Delete(files[0]);
        }

        //删除目录中所有的子目录
        string[] dirs = Directory.GetDirectories(directoryPath);
        for (int i = 0; i < dirs.Length; i++)
        {
            Directory.Delete(dirs[i]);
        }
    }

    /// <summary> 
    /// 获取一个文件的长度,单位为Byte 
    /// </summary> 
    /// <param name="filePath">文件的绝对路径</param>         
    public static long GetFileSize(string filePath)
    {
        //创建一个文件对象 
        FileInfo fi = new(filePath);
        //获取文件的大小 
        return fi.Length;
    }

    /// <summary>
    /// 获取所有文件夹及子文件夹
    /// </summary>
    /// <param name="dirPath"></param>
    /// <returns></returns>
    public static List<TreeFile> GetDirAllFiles(string dirPath)
    {
        int zdId = 0;

        var list = new List<TreeFile>();
        return GetArrys(dirPath, 0, list);

        List<TreeFile> GetArrys(string dirPath, int pid, List<TreeFile> list)
        {
            if (!Directory.Exists(dirPath)) return list;
            if (Directory.GetDirectories(dirPath).Length <= 0) return list;

            foreach (string path in Directory.GetDirectories(dirPath))
            {
                zdId++;
                var model = new TreeFile()
                {
                    id = zdId,
                    name = Path.GetFileName(path),
                    pId = pid,
                    open = false,
                    target = "DeployBase",
                    url = path
                };
                list.Add(model);
                GetArrys(path, model.id, list);
            }
            return list;
        }
    }

    /// <summary>
    /// 重命名文件
    /// </summary>
    public static void FileReName(string sourcePath, string newPath)
    {
        Directory.Move(sourcePath, newPath);
    }

    /// <summary>
    /// 读取文件内容，如果文件不存在，则返回空。
    /// </summary>
    /// <param name="filepath">文件路径</param>
    /// <returns></returns>
    public static string ReadTextIgnoreExists(string filepath)
    {
        if (!File.Exists(filepath))
        {
            return "";
        }

        return File.ReadAllText(filepath);
    }

    /// <summary>
    /// 写入内容到文件，如果目录不存在则创建
    /// </summary>
    /// <param name="dirPath">文件目录</param>
    /// <param name="fileName">文件名称</param>
    /// <param name="content">写入的内容</param>
    /// <param name="appendToLast">是否将内容添加到未尾,默认不添加</param>
    public static void CreateDirAndWriteText(string dirPath, string fileName, string content, bool appendToLast = false)
    {
        CreateDirectoryIfNotExists(dirPath);

        if (appendToLast)
        {
            File.AppendAllText(Path.Combine(dirPath, fileName), content);
        }
        else
        {
            File.WriteAllText(Path.Combine(dirPath, fileName), content);
        }
    }

    #region 获得文件目录

    public static List<FileFolder> GetFileDirectory(string path)
    {
        try
        {
            var di = new DirectoryInfo(path);
            var list = new List<FileFolder>()
            {
                new FileFolder()
                {
                    Path = "根目录",
                    Children = GetFileDirectoryNode(di, "")
                }
            };
            return list;
        }
        catch (Exception)
        {
            return new List<FileFolder>()
            {
                new FileFolder()
                {
                    Path = "根目录",
                    Children = null
                }
            };
        }

        static List<FileFolder> GetFileDirectoryNode(DirectoryInfo dirInfo, string path)
        {
            return dirInfo.GetDirectories().Select(s => new FileFolder()
            {
                Path = s.Name,
                Routes = Path.Combine(path, s.Name),
                Children = GetFileDirectoryNode(s, Path.Combine(path, s.Name)),
            }).ToList();
        }
    }

    #endregion

    #region 获得文件目录下的文件，支持子目录

    /// <summary>
    /// 获得指定文件夹下面的所有文件
    /// </summary>
    /// <param name="path"></param>
    /// <param name="fileType"></param>
    /// <param name="staticFiles"></param>
    /// <returns></returns>
    public static List<FileContentInfo> ResolveFileInfo(string path, string fileType, string staticFiles = "")
    {
        var files = new List<FileContentInfo>();

        foreach (var fsi in new DirectoryInfo(path).GetFiles())
        {
            var fileExt = GetFileExt(fsi.Name);
            switch (string.IsNullOrEmpty(fileType))
            {
                case false when fileType == "image" && IsImage(fileExt):
                case false when fileType == "file" && !IsImage(fileExt):
                    files.Add(new FileContentInfo()
                    {
                        Name = fsi.Name,
                        FullName = fsi.FullName,
                        FileExt = fsi.Extension,
                        FileOriginalSize = fsi.Length,
                        FileSize = FileSizeTransf(fsi.Length),
                        FileName = fsi.FullName.Replace(staticFiles, ""),
                        CreateDate = fsi.CreationTime,
                        LastWriteDate = fsi.LastWriteTime,
                        LastAccessDate = fsi.LastAccessTime
                    });
                    break;
                default:
                    {
                        if (string.IsNullOrEmpty(fileType))
                        {
                            files.Add(new FileContentInfo()
                            {
                                Name = fsi.Name,
                                FullName = fsi.FullName,
                                FileExt = fsi.Extension,
                                FileOriginalSize = fsi.Length,
                                FileSize = FileSizeTransf(fsi.Length),
                                FileName = fsi.FullName.Replace(staticFiles, ""),
                                CreateDate = fsi.CreationTime,
                                LastWriteDate = fsi.LastWriteTime,
                                LastAccessDate = fsi.LastAccessTime
                            });
                        }

                        break;
                    }
            }
        }

        string[] folders = Directory.GetDirectories(path, "*", SearchOption.AllDirectories);
        foreach (var folder in folders)
        {
            foreach (var fsi in new DirectoryInfo(folder).GetFiles())
            {
                var fileExt = GetFileExt(fsi.Name);
                switch (string.IsNullOrEmpty(fileType))
                {
                    case false when fileType == "image" && IsImage(fileExt):
                    case false when fileType == "file" && !IsImage(fileExt):
                        files.Add(new FileContentInfo()
                        {
                            Name = fsi.Name,
                            FullName = fsi.FullName,
                            FileExt = fsi.Extension,
                            FileOriginalSize = fsi.Length,
                            FileSize = FileSizeTransf(fsi.Length),
                            FileName = fsi.FullName.Replace(staticFiles, ""),
                            CreateDate = fsi.CreationTime,
                            LastWriteDate = fsi.LastWriteTime,
                            LastAccessDate = fsi.LastAccessTime
                        });
                        break;
                    default:
                        {
                            if (string.IsNullOrEmpty(fileType))
                            {
                                files.Add(new FileContentInfo()
                                {
                                    Name = fsi.Name,
                                    FullName = fsi.FullName,
                                    FileExt = fsi.Extension,
                                    FileOriginalSize = fsi.Length,
                                    FileSize = FileSizeTransf(fsi.Length),
                                    FileName = fsi.FullName.Replace(staticFiles, ""),
                                    CreateDate = fsi.CreationTime,
                                    LastWriteDate = fsi.LastWriteTime,
                                    LastAccessDate = fsi.LastAccessTime
                                });
                            }

                            break;
                        }
                }
            }
        }

        return files;
    }

    /// <summary>
    ///  文件大小转为B、KB、MB、GB...
    /// </summary>
    /// <param name="size"></param>
    /// <returns></returns>
    public static string FileSizeTransf(long size)
    {
        string[] units = { "B", "KB", "MB", "GB", "TB", "PB" };

        long mod = 1024;
        int i = 0;
        while (size > mod)
        {
            size /= mod;
            i++;
        }

        return size + units[i];
    }

    #endregion

    #region 文件格式

    /// <summary>
    /// 是否可添加水印
    /// </summary>
    /// <param name="fileExt">文件扩展名，不含“.”</param>
    /// <returns></returns>
    public static bool IsCanWater(string fileExt)
    {
        string[] images = { "jpg", "jpeg" };
        return images.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 是否为图片
    /// </summary>
    /// <param name="fileExt">文件扩展名，不含“.”</param>
    /// <returns></returns>
    public static bool IsImage(string fileExt)
    {
        string[] images = { "bmp", "gif", "jpg", "jpeg", "png" };
        return images.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 是否为视频
    /// </summary>
    /// <param name="fileExt">文件扩展名，不含“.”</param>
    /// <returns></returns>
    public static bool IsVideos(string fileExt)
    {
        string[] videos = { "rmvb", "mkv", "ts", "wma", "avi", "rm", "mp4", "flv", "mpeg", "mov", "3gp", "mpg" };
        return videos.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 是否为音频
    /// </summary>
    /// <param name="fileExt">文件扩展名，不含“.”</param>
    /// <returns></returns>
    public static bool IsMusics(string fileExt)
    {
        string[] musics = { "mp3", "wav" };
        return musics.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    /// <summary>
    /// 是否为文档
    /// </summary>
    /// <param name="fileExt">文件扩展名，不含“.”</param>
    /// <returns></returns>
    public static bool IsDocument(string fileExt)
    {
        string[] documents = { "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt", "pdf" };
        return documents.Contains(fileExt, StringComparer.OrdinalIgnoreCase);
    }

    #endregion
}
